﻿

<#
   .SYNOPSIS 
   Gets a client proxy to the FIM CM Extension Proxy

   .DESCRIPTION
   The Get-FimCmExtensionProxy function connects to the FIM CM Service using
   a .NET Remoting proxy.

   .OUTPUTS
   A client proxy for the FIM CM Extensions
#>
Function Get-FimCmExtensionProxy
{
	###
	### The assemblies we need to load are likely to be in one of three places:
	###   1. The FIM Service folder
	###	  2. The FIM CM web\bin folder
	###   3. THIS folder, DUH!
	
	###
	### Determine if we are running on the FIM Service box or the FIM CM box
	###
	$assemblyFolder = $PWD
	if (Test-Path HKLM:\SYSTEM\CurrentControlSet\Services\FIMService)
	{
		$fimImagePath = (Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\FIMService).ImagePath
		$assemblyFolder = Split-Path -Path ($fimImagePath -Replace '"', $null)
	}
	elseif (Test-Path HKLM:\SOFTWARE\Microsoft\CLM\v1.0\Setup)
	{
		$fimImagePath = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\CLM\v1.0\Setup).WebFolder
		$assemblyFolder = Join-Path $fimImagePath bin
	}

	###
	### Load the FIM CM Extension Proxy Assembly, and the .NET Remoting Assembly
	###
	[reflection.Assembly]::LoadFrom((Join-Path $assemblyFolder 'FimCmExtensions.FimCmProxy.dll')) | Out-Null
	[reflection.Assembly]::LoadFrom('C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Runtime.Remoting.dll') | Out-Null
	[reflection.Assembly]::LoadFrom((Join-Path $assemblyFolder 'Microsoft.Clm.Shared.dll')) | Out-Null
	[reflection.Assembly]::LoadFrom((Join-Path $assemblyFolder 'Microsoft.Clm.Common.dll')) | Out-Null
	
	###
	### Set up the remoting infrastructure
	###
	if ([System.Runtime.Remoting.Channels.ChannelServices]::GetChannel('ClmHttpChannel') -eq $null)
	{
	    $clmUrl = 'http://cm/certificatemanagement/FimCmProxy.rem'
	    $binaryClientFormatterSinkProvider = new-object System.Runtime.Remoting.Channels.BinaryClientFormatterSinkProvider
	    $httpClientChannel = New-Object System.Runtime.Remoting.Channels.Http.HttpClientChannel('ClmHttpChannel', $binaryClientFormatterSinkProvider)
	    [System.Runtime.Remoting.Channels.ChannelServices]::RegisterChannel($httpClientChannel, $true)
	    [System.Runtime.Remoting.RemotingConfiguration]::RegisterWellKnownClientType([FimCmExtensions.FimCmProxy], $clmUrl)
	}

	$FimCmProxy = New-Object FimCmExtensions.FimCmProxy

	###
	### Supply the credentials for connecting to CLM
	###
	$channelProperties = [System.Runtime.Remoting.Channels.ChannelServices]::GetChannelSinkProperties($FimCmProxy)
	$clmUri = [System.Runtime.Remoting.RemotingServices]::Marshal($FimCmProxy).URI
	$credentialCache = New-Object System.Net.CredentialCache
	$credentialCache.Add($clmUri,'ntlm',[System.Net.CredentialCache]::DefaultCredentials)
	$channelProperties.credentials = [System.Net.CredentialCache]$credentialCache
	
	###
	### TODO: Check the service status
	###

	Write-Output $FimCmProxy
}

<#
   .SYNOPSIS 
   Verifies the Enroll Permission for a USer on a Profile Template

   .DESCRIPTION
   Connects to the FIM CM service to check the user rights on a given profile template

   .OUTPUTS
   TRUE if the user has rights
   FALSE if the user does not have rights
   Exceptions if the user does not exist or the profile template does not exist
#>
Function Assert-EnrollRights
{
   Param
   (        
        [parameter(Mandatory=$true)]
        [String]
        $TargetUserName,
        
        [parameter(Mandatory=$true)]
        [String]
        $ProfileTemplateName
    ) 
    
    Begin
    {        
        ###
        ### Connect to the CM Server service
        ###
        Write-Verbose "Connecting to the CM service..."
        $fimCmProxy = Get-FimCmExtensionProxy
		
			    ###
        ### Check the Rights
        ###
        Write-Verbose "Check the Rights for $TargetUserName..."
        $fimCmProxy.CheckEnrollProfileTemplateRights($TargetUserName, $ProfileTemplateName)  
    }#Begin
}#Function Assert-EnrollRights

<#
   .SYNOPSIS 
   Initiates an Enroll Request for a User on a Profile Template

   .DESCRIPTION
   Connects to the FIM CM service to Enroll the user for a given profile template

   .OUTPUTS
   the GUID of the new Request
   Exceptions if the user does not exist or the profile template does not exist
#>
Function Add-EnrollRequest
{
   Param
   (        
        [parameter(Mandatory=$true)]
        [String]
        $TargetUserName,
        
        [parameter(Mandatory=$true)]
        [String]
        $ProfileTemplateName
    ) 
    
    Begin
    {        
        ###
        ### Connect to the CM Server service
        ###
        Write-Verbose "Connecting to the CM service..."
        $fimCmProxy = Get-FimCmExtensionProxy
		
		###
        ### Check the Rights
        ###
        Write-Verbose "Enroll $TargetUserName for $ProfileTemplateName..."
        $fimCmProxy.InitiateEnrollRequest($TargetUserName, $ProfileTemplateName)  
    }#Begin
}#Function Add-EnrollRequest


<#
   .SYNOPSIS 
   Tests the Connection to the FIM CM .NET Remoting Object

   .DESCRIPTION
   Connects to the FIM CM service at the endpoint where our .NET Proxy is configured

   .OUTPUTS
   TRUE if the connection is made
   FALSE otherwise
#>
Function Test-FimCmProxyConnection
{
	Begin
	{
		$fimCmExtensionUrl = "http://cm/certificatemanagement/FimCmProxy.rem?wsdl"
		
		Write-Verbose ("Connecting to FIM CM Extension Proxy at: {0}" -F $fimCmExtensionUrl)		
		Write-Verbose "Using the current user as credentials."
		Write-Verbose "Using NTLM as the authentication type."
		$credentialCache = New-Object System.Net.CredentialCache
		$credentialCache.Add($fimCmExtensionUrl,'ntlm',[System.Net.CredentialCache]::DefaultCredentials)
		 
		$webRequest = [System.Net.WebRequest]::Create($fimCmExtensionUrl) 
		$webRequest.Credentials = $credentialCache
		$statusCode = $webRequest.GetResponse().StatusCode
		
		if ($statusCode -eq 'OK')
		{
			return $true
		}
		else
		{
			return $false
		}
	}
}

<#
   .SYNOPSIS 
   Gets a CM Request Object by GUID

   .DESCRIPTION
   Connects to the FIM CM service to get a CM Request

   .OUTPUTS
   the Request object   
#>
Function Get-RequestByGuid
{
   Param
   (        
        [parameter(Mandatory=$true)]        
        $RequestGuid
    ) 
    
    Begin
    {        
        ###
        ### Connect to the CM Server service
        ###
        Write-Verbose "Connecting to the CM service..."
        $fimCmProxy = Get-FimCmExtensionProxy
		
		if ($RequestGuid -is [Guid])
		{
			## Already a GUID, nice input!
		}
		elseif ($RequestGuid -is [String])
		{
			## Change to GUID
			$RequestGuid = [Guid]$RequestGuid
		}
		else
		{
			Write-Error "Sorry, unhandled input type. Was hoping for a GUID or String..."
		}
		
		###
        ### Get the Request
        ###
        Write-Verbose ("Getting Request for Guid {0}..." -f $RequestGuid)
        Write-Output $fimCmProxy.GetRequestByGuid($RequestGuid)  
    }#Begin
}#Function Get-RequestByGuid

<#
   .SYNOPSIS 
   Gets the Request Secrets for a CM Request

   .DESCRIPTION
   Connects to the FIM CM service to get Request Secrets

   .OUTPUTS
   the Request Secrets   
#>
Function Get-RequestSecrets
{
   Param
   (        
        [parameter(Mandatory=$true)]        
        $RequestGuid
    ) 
    
    Begin
    {        
        ###
        ### Connect to the CM Server service
        ###
        Write-Verbose "Connecting to the CM service..."
        $fimCmProxy = Get-FimCmExtensionProxy
		
		###
        ### Get the Request
        ###
        Write-Verbose ("Getting Request Secrets for Request Guid {0}..." -f $RequestGuid)
		$Request = Get-RequestByGuid $RequestGuid
		
        Write-Output $fimCmProxy.GetRequestSecrets($Request.Uuid) 
    }#Begin
}#Function Get-RequestSecrets

<#
   .SYNOPSIS 
   Gets CM Profile Template Objects

   .DESCRIPTION
   Connects to the FIM CM service to get the CM Profile Templates
   This is a simple wrapper for the Provision API FindAllProfileTemplates() method

   .OUTPUTS
   the Profile Templates   
#>
Function Get-ProfileTemplates
{
    Begin
    {        
        ###
        ### Connect to the CM Server service
        ###
        Write-Verbose "Connecting to the CM service..."
        $fimCmProxy = Get-FimCmExtensionProxy
		
		###
        ### Get the ProfileTemplates
        ###
        Write-Verbose "Getting Profile Templates..."
        Write-Output $fimCmProxy.FindAllProfileTemplates() 
    }#Begin
}#Function Get-ProfileTemplates

<#
   .SYNOPSIS 
   Gets a CM Profile Object by GUID

   .DESCRIPTION
   Connects to the FIM CM service to get a CM Profile

   .OUTPUTS
   the Profile object   
#>
Function Get-ProfileByGuid
{
   Param
   (        
        [parameter(Mandatory=$true)]        
        $ProfileGuid
    ) 
    
    Begin
    {        
        ###
        ### Connect to the CM Server service
        ###
        Write-Verbose "Connecting to the CM service..."
        $fimCmProxy = Get-FimCmExtensionProxy
		
		if ($ProfileGuid -is [Guid])
		{
			## Already a GUID, nice input!
		}
		elseif ($ProfileGuid -is [String])
		{
			## Change to GUID
			$ProfileGuid = [Guid]$ProfileGuid
		}
		else
		{
			Write-Error "Sorry, unhandled input type. Was hoping for a GUID or String..."
		}
		
		###
        ### Get the Profile
        ###
        Write-Verbose ("Getting Profile for Guid {0}..." -f $ProfileGuid)
        Write-Output $fimCmProxy.GetProfile($ProfileGuid)  
    }#Begin
}#Function Get-ProfileByGuid

<#
   .SYNOPSIS 
   Suspend a CM Profile Object by GUID

   .DESCRIPTION
   Connects to the FIM CM service to Suspend a CM Profile

   .OUTPUTS
   the Request object   
#>
Function Suspend-ProfileByGuid
{
   Param
   (        
        [parameter(Mandatory=$true)]        
        $ProfileGuid,
		
		[parameter(Mandatory=$false)]        
        [String]
		$Comment = "Suspension"
    ) 
    
    Begin
    {        
        ###
        ### Connect to the CM Server service
        ###
        Write-Verbose "Connecting to the CM service..."
        $fimCmProxy = Get-FimCmExtensionProxy
		
		$profile = Get-ProfileByGuid -ProfileGuid $ProfileGuid
		
		###
        ### Suspend the Profile
        ###
        Write-Verbose ("Suspending Profile Guid {0}..." -f $profile.Uuid)
        Write-Output $fimCmProxy.SuspendProfile($profile.Uuid, $Comment)  
    }#Begin
}#Function Suspend-ProfileByGuid

<#
   .SYNOPSIS 
   Reinstate a CM Profile Object by GUID

   .DESCRIPTION
   Connects to the FIM CM service to Reinstate a CM Profile

   .OUTPUTS
   the Request object   
#>
Function Reinstate-ProfileByGuid
{
   Param
   (        
        [parameter(Mandatory=$true)]        
        $ProfileGuid,
		
		[parameter(Mandatory=$false)]        
        [String]
		$Comment = "Reinstated"
    ) 
    
    Begin
    {        
        ###
        ### Connect to the CM Server service
        ###
        Write-Verbose "Connecting to the CM service..."
        $fimCmProxy = Get-FimCmExtensionProxy
		
		$profile = Get-ProfileByGuid -ProfileGuid $ProfileGuid
		
		###
        ### Suspend the Profile
        ###
        Write-Verbose ("Reinstating Profile Guid {0}..." -f $profile.Uuid)
        Write-Output $fimCmProxy.ReinstateProfile($profile.Uuid, $Comment)  
    }#Begin
}#Function Reinstate-ProfileByGuid